package com.huangwenshuo.futurestarschoolmanagement.security;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huangwenshuo.futurestarschoolmanagement.config.RedisService;
import com.huangwenshuo.futurestarschoolmanagement.pojo.dto.JwtUserDto;
import com.huangwenshuo.futurestarschoolmanagement.utils.JwtTokenUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
    UrlGrantedAuthority urlGrantedAuthority = new UrlGrantedAuthority();

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {

        String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
        // 如果请求头中没有Authorization信息则直接放行了
        if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        // 如果请求头中有token，则进行解析，并且设置认证信息
        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        RedisService redisService= (RedisService) factory.getBean("redisService");
        try {
            SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader,redisService));
        } catch (TokenIsExpiredException e) {
            //返回json形式的错误信息
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            String reason = "{" +
                    "\"status\": 403," +
                    "\"msg\": \"访问失败:"+e.getMessage()+"\"" +
                    "}";
            response.getWriter().write(reason);
            response.getWriter().flush();
            return;
        }

        try {
            request.setAttribute("uid",JwtTokenUtils.getUid(tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "")));
        } catch (TokenIsExpiredException e) {
            logger.error("token获取uid失败");
            e.printStackTrace();
        }
        super.doFilterInternal(request, response, chain);
    }

    // 这里从token中获取用户信息并新建一个token
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader,RedisService redisService) throws TokenIsExpiredException {
        String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");
//        boolean expiration = JwtTokenUtils.isExpiration(token);
        boolean expiration = RedisCheckUser(JwtTokenUtils.getUsername(token),redisService)==null?true:false;

        if (expiration) {
            throw new TokenIsExpiredException("token失效了");
        } else {
            String username = JwtTokenUtils.getUsername(token);
            List role = JwtTokenUtils.getUserRole(token);
            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            //把role里的值取出来，然后组装成UrlGrantedAuthority
            for (int i =0;i<role.size();i++) {
                if (role.get(i) != null) {
                    urlGrantedAuthority = SplitRole((String)role.get(i));

                    GrantedAuthority grantedAuthority = new UrlGrantedAuthority(urlGrantedAuthority.getPermissionUrl(),urlGrantedAuthority.getMethod());

                    grantedAuthorities.add(grantedAuthority);
                }
            }
            if (username != null) {
                return new UsernamePasswordAuthenticationToken(username, null, grantedAuthorities);
            }
        }
        return null;
    }

    public  JwtUserDto RedisCheckUser(String username,RedisService redisService) {

        //从redis里边取出用户信息
        String stringValue = redisService.get("fssm"+":"+username);

        if (stringValue != null) {
            try {
                // 验证当前请求的session是否是已登录的session
                //json转成JwtUser对象
                JwtUserDto jwtUserDto = JSONObject.parseObject(stringValue,JwtUserDto.class);
                return jwtUserDto;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }

    private UrlGrantedAuthority SplitRole(String urlG){
        String[] roleString = StringUtils.split(urlG,";");
        urlGrantedAuthority.setPermissionUrl(roleString[0]);
        urlGrantedAuthority.setMethod(roleString[1]);
        return urlGrantedAuthority;
    }
}
